----------------------------------------------------------------------------------
-- Company: Ensimag
-- Engineers: Muller, Viardot, Mancini
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PC is
  Port (
    CLK     : in  STD_LOGIC;
    RESET   : in  STD_LOGIC;
    RST     : out  STD_LOGIC;

    SelRa   : out  std_logic_vector(2 downto 0);			  
    SelRb   : out  std_logic_vector(2 downto 0);			  
    SelRd   : out  std_logic_vector(2 downto 0);			  
    SelRin  : out  std_logic_vector(1 downto 0);			  			  
    ERd     : out  STD_LOGIC;
    EOUT    : out  STD_LOGIC;			  

    CLRPC   : out  STD_LOGIC;
    EPC     : out  STD_LOGIC;
    LDPC    : out  STD_LOGIC;
    SelPC   : out  STD_LOGIC;
    
    selA    : out  STD_LOGIC;
    selB    : out  STD_LOGIC;
    ImmB     : out STD_LOGIC_VECTOR(15 downto 0);
    
    op      : out std_logic_vector(5 downto 0);
    ECarry  : out STD_LOGIC;
    
    EIR     : out  STD_LOGIC;
    IR      : in STD_LOGIC_VECTOR(15 downto 0);
    
    selCond : out  STD_LOGIC_VECTOR (2 downto 0);
    cond    : in STD_LOGIC;
    
    
    WE      : out  STD_LOGIC;
    CE      : out  STD_LOGIC;
    OE      : out  STD_LOGIC
    
    );
end PC;

architecture RTL of PC is

-- Signaux de la PC
  type StateType is (st_Fetch,
		     st_JumpPreFetch,
		     st_Decode,
		     st_Reset,
		     st_In,
			  st_OUT,
			  st_OP,
			  st_LW,
			  st_LW1,
			  st_SW,
			  st_BRCC,
			  st_BACC,
			  st_BRICC,
			  st_LI,
			  st_BRL,
			  st_BRL1,
			  st_BAL
		     -- A COMPLETER
		     );
  
  signal NEXT_STATE,current_state : StateType;

begin

  Registres_Partie_Controle:	
  process (CLK,RESET) 
  begin 
    if (RESET='1') then 
      current_state<= st_reset;
    elsif (clk'event and clk='1') then 
      current_state <= next_state;
    end if;
  end process Registres_Partie_Controle ;	

  process (current_state, IR, cond)  		-- a compléter
    
  begin
    RST    <= '0';
    SelRd  <= IR(2 downto 0);
	 SelRa  <= IR(5 downto 3);
	 SelRb <= IR(8 downto 6);
    SelRin <= (others=>'0');
	 SelCond <= "111";
	 
	 op <= IR(14 downto 9);
	 
    ERd    <= '0';
    EOUT   <= '0';

    CLRPC  <= '0';
    EPC    <= '0';
    LDPC   <= '0';
    SelPC  <= '0';

    selA    <= '0';
    selB    <= '0';
    ImmB     <= (others=>'0');

    
    ECarry <= '0';

    EIR    <= '0';

    

    WE     <= '0';
    CE     <= '0';
    OE      <= '0';
    -- A COMPLETER
    -- AJOUTER AUTRES SIGNAUX
    
    
    next_state<= st_fetch;

    case current_state is
      -- Il faut préciser les valeurs pour tous les etats!!!
      when st_fetch =>
			EIR <= '1';
			NEXT_STATE <= st_decode;

      when st_JumpPreFetch =>
			-- Expliquer à quoi sert cet état
			NEXT_STATE <= st_Fetch ;

	
      when st_decode =>
			EPC<='1';
			if IR = X"FFFF" then NEXT_STATE <= st_reset;
			elsif IR(15 downto 9) = "1101010" then NEXT_STATE <= st_IN;
			elsif IR(15 downto 9) = "1101011" then NEXT_STATE <= st_OUT;
			elsif IR(15 downto 9) = "1101000" then NEXT_STATE <= st_LW;
			elsif IR(15 downto 9) = "1101001" then NEXT_STATE <= st_SW;
			elsif IR(15 downto 9) = "1110000" then NEXT_STATE <= st_BRCC;
			elsif IR(15 downto 9) = "1110001" then NEXT_STATE <= st_BACC;
			elsif IR(15 downto 14) = "10" then NEXT_STATE <= st_BRICC;
			elsif IR(15 downto 12) = "1100" then NEXT_STATE <= st_LI;
			elsif IR(15 downto 9) = "1111000" then NEXT_STATE <= st_BRL;
			elsif IR(15 downto 9) = "1111001" then NEXT_STATE <= st_BAL;
			elsif IR(15) = '0' then
				NEXT_STATE <= st_OP;
			end if;
	
      when st_reset =>
			RST<='1';
	
      when st_IN =>
			ERd<='1';
			SelRin<="11";
	
	   when st_OUT =>
			EOUT<='1';
	
		when st_OP =>
			selA<='1';
			selB<='1';
			ERd<='1';
			ECarry<='1';
			-- SelRin est déjà à 00
			
		when st_LW =>
			op<="001000";
			selA<='1';
			OE<='1';
			CE<='1';
			NEXT_STATE<=st_LW1;
			
		when st_LW1 =>
			SelRin<="01";
			ERd<='1';
			
		when st_SW =>
			SelA <= '1';
			op <= "001000";
			CE <= '1'; 
			WE <='1';
			
		when st_BRCC =>
			SelB <= '1';
			SelCond <= IR(2 downto 0);
			-- SelA <= '0' on selectionne sPC
			-- on choisie l'opération addition
			op <= "000100";
			if Cond = '1' then
			   LDPC <= '1';
				EPC <= '1';
			end if;
			NEXT_STATE <= st_JumpPreFetch;
		
		when st_BACC =>
			SelB <= '1';
			SelCond <= IR(2 downto 0);
			-- SelA <= '0' on selectionne sPC
			-- on choisie l'opération addition
			op <= "000100";
			-- on met rb dans pc
			SelPC <= '1';
			if Cond = '1' then
			   LDPC <= '1';
				EPC <= '1';
			end if;
			NEXT_STATE <= st_JumpPreFetch;
		
		when st_BRICC =>
			-- SelB <= '0', on selectionne imm8
			SelCond <= IR(2 downto 0);
			-- SelA <= '0' on selectionne sPC
			immB <= "00000000" & IR(13 downto 6);
			-- on choisie l'opération addition
			op <= "000100";
			if Cond = '1' then
			   LDPC <= '1';
				EPC <= '1';
			end if;
			NEXT_STATE <= st_JumpPreFetch;
			
		when st_LI =>
			ImmB <= "0000000" & IR(11 downto 3);
			-- SelB <= '0'
			-- movb
			op <= "001001";
			-- SelRin <= "00"
			ERd <= '1';
			
		when st_BRL =>
			op <= "001000";
			ERd <= '1';
			NEXT_STATE<=st_BRL1;
		
		when st_BRL1 =>
			SelB <= '1';
			op <= "000100";
			LDPC <= '1'; 
			EPC <='1';
			NEXT_STATE<=st_JumpPreFetch;
			
		when st_BAL =>
			op <= "001000";
			ERd <= '1';
			SelPC <= '1';
			LDPC <= '1';
			EPC<='1';
				
			NEXT_STATE<=st_JumpPreFetch;
			
	
	-- A COMPLETER
	-- AJOUTER DES ETATS
    end case;
  end process;
end RTL;
